home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2006 March / PCWMAR06.iso / Software / Freeware / Thingamablog 1.0.5 / thinga-setup-1.0.5.exe / tb_legacy.jar / Blog.java < prev    next >
Encoding:
Java Source  |  2004-08-02  |  32.2 KB  |  1,073 lines

  1. /*
  2.  * Copyright (C) 2003  Bob Tantlinger
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  * 
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  *
  18.  */
  19.  
  20. import java.sql.*;
  21. import java.util.*;
  22. import java.io.*;
  23. //import com.tantlinger.*;
  24.  
  25. public class Blog extends BlogDB implements Serializable
  26. {
  27.     static final long serialVersionUID = 8562495511007798201L;
  28.     
  29.     public static int ARCHIVE_MONTHLY = 0;
  30.     public static int ARCHIVE_WEEKLY = 1;
  31.     public static int ARCHIVE_BY_DAY_INTERVAL = 2;    
  32.     private static final String ASC = "ASC";
  33.     private static final String DESC = "DESC";    
  34.     public static final String RSS_FILENAME = "rss.xml";
  35.     
  36.     private int archivePolicy = ARCHIVE_MONTHLY;
  37.     
  38.     private String ascOrDesc = DESC;
  39.     private int daysInterval = 5;
  40.     private java.util.Date baseDate;
  41.     
  42.     private boolean arcListAscending;
  43.     private boolean generateRss = true;
  44.         
  45.     private boolean limitFrontPageEntries = true;
  46.     private int frontPageEntryLimit = 10;    
  47.     private boolean limitCatPageEntries = true;
  48.     private int catPageEntryLimit = 10;    
  49.     
  50.     private Vector updatedPages = new Vector();
  51.     private DatedArchivePage curArcPage;
  52.     
  53.     private File baseDir;    
  54.     private File htmlDir;
  55.     private File arcsDir;
  56.     private File templateDir;
  57.     
  58.     private File pageTmp;
  59.     private File arcTmp;
  60.     private File indexTmp;
  61.     
  62.     private java.util.Date lastPublishDate;
  63.     
  64.     private boolean isWriteFullRssEntries;
  65.     
  66.     BlogVariables vars = new BlogVariables();
  67.     
  68.     public Blog(File dir)
  69.     {
  70.         setBaseDate(new java.util.Date());
  71.         setBaseDirectory(dir);
  72.     }
  73.     
  74.     public BlogVariables getBlogVariables()
  75.     {
  76.         return vars;    
  77.     }
  78.     
  79.     public void setBlogVariables(BlogVariables v)
  80.     {
  81.         vars = v;
  82.     }
  83.     
  84.     public void setArchivePolicy(int p)
  85.     {
  86.         archivePolicy = p;    
  87.     }
  88.     
  89.     public int getArchivePolicy()
  90.     {
  91.         return archivePolicy;    
  92.     }
  93.     
  94.     public void setBaseDirectory(File dir)
  95.     {        
  96.         DatedArchivePage.setArchiveRangeFormat(vars.getArchiveRangeFormat());
  97.         DatedArchivePage.setListAscending(arcListAscending);
  98.         
  99.         if(dir == null || !dir.isDirectory())
  100.             return;
  101.                
  102.         baseDir = dir;
  103.         dbDir = new File(baseDir.getAbsolutePath() + SEP + "DB");
  104.         htmlDir = new File(baseDir.getAbsolutePath() + SEP + "html");
  105.         arcsDir = new File(htmlDir.getAbsolutePath() + SEP + "archives");        
  106.         
  107.         templateDir = new File(baseDir.getAbsolutePath() + SEP + "templates");
  108.         if(!htmlDir.exists())
  109.             htmlDir.mkdir();
  110.         if(!arcsDir.exists())
  111.             arcsDir.mkdir();
  112.         if(!dbDir.exists())
  113.             dbDir.mkdir(); 
  114.         if(!templateDir.exists())
  115.             templateDir.mkdir();
  116.         
  117.         setTemplateDirectory(templateDir);               
  118.     }
  119.     
  120.     public File getBaseDirectory()
  121.     { 
  122.         return baseDir; 
  123.     }
  124.     
  125.     protected void addToUpdated(File f)
  126.     {
  127.         if(!updatedPages.contains(f))
  128.             updatedPages.add(f);
  129.     }
  130.     
  131.     public File[] getUpdatedPages()
  132.     {
  133.         if(updatedPages.size() == 0)
  134.             return null;
  135.         
  136.         File f[] = new File[updatedPages.size()];
  137.         for(int i = 0; i < f.length; i++)
  138.             f[i] = (File)updatedPages.elementAt(i);
  139.         
  140.         return f;
  141.     }
  142.     
  143.     public void removeUpdatedPage(File f)
  144.     {
  145.         updatedPages.remove(f);    
  146.     }
  147.     
  148.     public void clearUpdatedPages()
  149.     {
  150.         updatedPages.removeAllElements();
  151.     }
  152.     
  153.     public void setTemplateDirectory(File d)
  154.     {
  155.         templateDir = d;
  156.         arcTmp = new File(templateDir.getAbsolutePath() + SEP + "archive.template");
  157.         pageTmp = new File(templateDir.getAbsolutePath() + SEP + "main.template");
  158.         indexTmp = new File(templateDir.getAbsolutePath() + SEP + "index.template");          
  159.     }
  160.     
  161.     public void setHtmlDirectory(File d)
  162.     {
  163.         htmlDir = d;
  164.     }
  165.     
  166.     public void setArchiveDirectory(File d)
  167.     {
  168.         arcsDir = d;
  169.     }
  170.     
  171.     public File getMainPage()
  172.     {
  173.         File f = new File(
  174.             getHtmlDirectory().getAbsolutePath() + SEP + vars.getMainPageFileName());
  175.         return f;
  176.     }
  177.     
  178.     public File getMainPageTemplate()
  179.     {
  180.         return pageTmp;
  181.     }
  182.     
  183.     public File getArchiveTemplate()
  184.     {
  185.         return arcTmp;
  186.     }
  187.     
  188.     public File getIndexTemplate()
  189.     {
  190.         return indexTmp;
  191.     }
  192.     
  193.     public File getHtmlDirectory()
  194.     {
  195.         return htmlDir;
  196.     }
  197.     
  198.     public File getTemplateDirectory()
  199.     {
  200.         return templateDir;
  201.     }
  202.     
  203.     public File getArchiveDirectory()
  204.     {
  205.         return arcsDir;
  206.     }
  207.     
  208.     protected String readTemplate(File t) throws IOException
  209.     {
  210.         String template = "";
  211.         BufferedReader reader = new BufferedReader(new FileReader(t));
  212.         String line;        
  213.         while((line = reader.readLine()) != null)
  214.             template += line + '\n';
  215.         
  216.         reader.close();
  217.         return template;
  218.     }
  219.         
  220.     protected void writeCategoryPages(String cats[]) throws IOException, SQLException
  221.     {
  222.         if(cats == null)
  223.         {
  224.             return;
  225.         }
  226.         for(int i = 0; i < cats.length; i++)
  227.             writeCategoryPage(cats[i]);
  228.     }
  229.     
  230.     protected void writeCategoryPage(String cat) throws IOException, SQLException
  231.     {    
  232.         File thePage = new CategoryPage(
  233.                getArchiveDirectory().getAbsolutePath(), cat);
  234.        String limit = "";
  235.        PreparedStatement ps;
  236.        
  237.        if(limitCatPageEntries)
  238.        {
  239.                ps = conn.prepareStatement
  240.             ("SELECT * FROM " + TABLE +
  241.              " WHERE " + CATEGORIES + " LIKE CONCAT('%', CONCAT(?, '%'))" +
  242.              " AND " + DRAFT + " = ? AND " + ARCPAGE + " <> ?");
  243.               ps.setString(1, "<" + cat + ">");
  244.               ps.setBoolean(2, false);
  245.               ps.setString(3, EXPIRED);       
  246.                limit = computeLimitArgument(ps, catPageEntryLimit);
  247.                ps.close(); 
  248.        }
  249.         
  250.         ps = conn.prepareStatement
  251.         ("SELECT " + limit + " * FROM " + TABLE +
  252.          " WHERE " + CATEGORIES + " LIKE CONCAT('%', CONCAT(?, '%')) " +
  253.          " AND " + DRAFT + " = ? AND " + ARCPAGE + " <> ?" +
  254.          " ORDER BY " + TIMESTAMP + ' ' + ascOrDesc);
  255.          ps.setString(1, "<" + cat + ">");
  256.          ps.setBoolean(2, false);
  257.            ps.setString(3, EXPIRED);  
  258.          ResultSet rs = ps.executeQuery();
  259.          
  260.         BlogPageWriter pw = new BlogPageWriter(
  261.             new FileWriter(thePage), arcsDir, vars, readTemplate(arcTmp),
  262.             cat, BlogPageWriter.CAT_OR_ARC);
  263.         
  264.         while(rs.next())
  265.         {
  266.             BlogEntryHeaderData hd = new BlogEntryHeaderData();
  267.             hd.setID(rs.getInt(ID));
  268.             hd.setTitle(rs.getString(TITLE));
  269.             hd.setTimestamp(rs.getTimestamp(TIMESTAMP));
  270.             hd.setAuthor(rs.getString(AUTHOR));
  271.             hd.setCategories(tokenizeCatString(rs.getString(CATEGORIES)));
  272.             hd.setLastModified(rs.getTimestamp(MODIFIED));
  273.             BlogEntry be = new BlogEntry(hd);
  274.             be.setEntryText(rs.getString(ENTRY));
  275.             pw.writeEntry(be, rs.getString(ARCPAGE));    
  276.         }
  277.         pw.closePage();
  278.         pw.close();
  279.         ps.close();
  280.         
  281.         addToUpdated(thePage);
  282.     }
  283.     
  284.     protected void writeIndexPage() throws IOException
  285.     {
  286.         File f = new File(
  287.             getHtmlDirectory().getAbsolutePath() +SEP+ vars.getIndexPageFileName());
  288.         BlogPageWriter pw = new BlogPageWriter(
  289.             new FileWriter(f), arcsDir, vars, readTemplate(indexTmp), "",
  290.             BlogPageWriter.INDEX);
  291.         
  292.         pw.closePage();    
  293.         pw.close();
  294.         
  295.         addToUpdated(f);           
  296.     }
  297.     
  298.     protected void writeArchivePage(String arcFileName) throws IOException, SQLException
  299.     {        
  300.         String title = "";
  301.         try
  302.         {
  303.             File arcFile = new File(arcsDir.getAbsolutePath() +SEP+ arcFileName);
  304.             DatedArchivePage dap = DatedArchivePage.createDatedArchivePage(arcFile);
  305.             title = dap.getTextString();
  306.         }
  307.         catch(Exception ex){}
  308.         
  309.         String query = "SELECT  * FROM " + TABLE + 
  310.             " WHERE " + ARCPAGE + " = " + "'" + arcFileName + "'" +
  311.             " AND " + DRAFT + " = '" + false + "'" +
  312.             " ORDER BY " + TIMESTAMP + ' ' + ascOrDesc;
  313.         
  314.         Statement st = conn.createStatement();
  315.         ResultSet rs = st.executeQuery(query);
  316.         File f = new File(arcsDir.getAbsolutePath() +SEP+ arcFileName);
  317.         BlogPageWriter pw = new BlogPageWriter(
  318.             new FileWriter(f), arcsDir, vars, readTemplate(arcTmp), title,
  319.             BlogPageWriter.CAT_OR_ARC);
  320.         
  321.         while(rs.next())
  322.         {
  323.             BlogEntryHeaderData hd = new BlogEntryHeaderData();
  324.             hd.setID(rs.getInt(ID));
  325.             hd.setTitle(rs.getString(TITLE));
  326.             hd.setTimestamp(rs.getTimestamp(TIMESTAMP));
  327.             hd.setAuthor(rs.getString(AUTHOR));
  328.             hd.setCategories(tokenizeCatString(rs.getString(CATEGORIES)));
  329.             hd.setLastModified(rs.getTimestamp(MODIFIED));
  330.             BlogEntry be = new BlogEntry(hd);
  331.             be.setEntryText(rs.getString(ENTRY));
  332.             pw.writeEntry(be, rs.getString(ARCPAGE));    
  333.         }
  334.         pw.closePage();
  335.         pw.close();
  336.         st.close();
  337.         
  338.         addToUpdated(f);        
  339.     }
  340.     
  341.     protected void writeBlogPage() throws IOException, SQLException
  342.     {
  343.         Timestamp ts = new Timestamp(baseDate.getTime());
  344.         String limit = "";
  345.         
  346.         if(limitFrontPageEntries)
  347.         {
  348.             PreparedStatement ps = conn.prepareStatement(
  349.             "SELECT  * FROM " + TABLE + 
  350.             " WHERE " + TIMESTAMP + " > ? AND " + DRAFT + " = ?" +
  351.             " AND " + ARCPAGE + " <> ?");
  352.             ps.setTimestamp(1, ts); 
  353.             ps.setBoolean(2, false);
  354.             ps.setString(3, EXPIRED);       
  355.             limit = computeLimitArgument(ps, frontPageEntryLimit);
  356.             ps.close();
  357.         }            
  358.         
  359.         String query = "SELECT " + limit + " * FROM " + TABLE + 
  360.             " WHERE " + TIMESTAMP + " > " + "'" + ts + "' AND " +
  361.             DRAFT + " = '" + false + "' AND " + 
  362.             ARCPAGE + " <> '" + EXPIRED + "'" +
  363.             " ORDER BY " + TIMESTAMP + ' ' + ascOrDesc;
  364.         
  365.         Statement st = conn.createStatement();
  366.         ResultSet rs = st.executeQuery(query);
  367.         File f = new File(getHtmlDirectory().getAbsolutePath() +SEP+ vars.getMainPageFileName());
  368.         BlogPageWriter pw = new BlogPageWriter(
  369.             new FileWriter(f), arcsDir, vars, readTemplate(pageTmp), "",
  370.             BlogPageWriter.FRONT_PAGE);        
  371.  
  372.         File rssFile = new File(assemblePath(
  373.             getHtmlDirectory().getAbsolutePath(), vars.getRssFileName()));    
  374.         RSSWriter rssw = new RSSWriter(rssFile, vars, isWriteFullRssEntries);
  375.         if(isGenerateRss())
  376.             rssw.writeHeader();
  377.         
  378.         while(rs.next())
  379.         {
  380.             BlogEntryHeaderData hd = new BlogEntryHeaderData();
  381.             hd.setID(rs.getInt(ID));
  382.             hd.setTitle(rs.getString(TITLE));
  383.             hd.setTimestamp(rs.getTimestamp(TIMESTAMP));
  384.             hd.setAuthor(rs.getString(AUTHOR));            
  385.             hd.setCategories(tokenizeCatString(rs.getString(CATEGORIES)));
  386.             hd.setLastModified(rs.getTimestamp(MODIFIED));
  387.             BlogEntry be = new BlogEntry(hd);
  388.             be.setEntryText(rs.getString(ENTRY));
  389.             String arcPage = rs.getString(ARCPAGE);
  390.             pw.writeEntry(be, arcPage);
  391.             if(isGenerateRss())
  392.                 rssw.writeEntry(be, arcPage);
  393.         }
  394.         pw.closePage();
  395.         pw.close();
  396.         if(isGenerateRss())
  397.         {        
  398.             rssw.writeFooter();
  399.             addToUpdated(rssFile);
  400.         }    
  401.         rssw.close();
  402.         st.close();       
  403.         addToUpdated(f);
  404.     }
  405.     
  406.     /** adds an entry to the DB */
  407.     public synchronized void addEntry(BlogEntry e) throws SQLException, IOException
  408.     {        
  409.         boolean update = false;
  410.         String arcPage = "";
  411.         curArcPage = getMostRecentDatedArchivePage();        
  412.         if(curArcPage == null || 
  413.             curArcPage.getExpirationDate().compareTo(e.getTimestamp()) < 0)
  414.         {
  415.            update = true;
  416.         }
  417.         else
  418.             arcPage = curArcPage.getName();
  419.         
  420.         PreparedStatement ps = conn.prepareStatement
  421.         (
  422.                 "INSERT INTO " + TABLE + "(" +
  423.                 TIMESTAMP + ", " +
  424.                 TITLE + ", " +
  425.                 CATEGORIES + ", " +
  426.                 ENTRY + ", " +
  427.                 DRAFT + ", " +
  428.                 MODIFIED + ", " +
  429.                 AUTHOR + ", " +
  430.                 ARCPAGE + ") " +
  431.                 "VALUES(?, ?, ?, ?, ?, ?, ?, ?)"
  432.         );
  433.         
  434.         ps.setTimestamp(1, e.getTimestamp());
  435.         ps.setString(2, e.getTitle());
  436.         ps.setString(3, catsString(e.getHeaderData().getCategories()));
  437.         ps.setString(4, e.getEntryText());
  438.         ps.setBoolean(5, e.getHeaderData().isDraft());
  439.         ps.setTimestamp(6, e.getHeaderData().getLastModified());
  440.         ps.setString(7, e.getHeaderData().getAuthor());
  441.         ps.setString(8, arcPage);
  442.         ps.executeUpdate();
  443.         ps.close();
  444.                 
  445.         if(update || e.isDraft())
  446.         {
  447.             System.out.println("Rebuilding Blog");
  448.             rebuildBlog();
  449.         }
  450.         else
  451.         {
  452.             System.out.println("Writing updated pages");
  453.             writeArchivePage(curArcPage.getName());
  454.             writeCategoryPages(e.getHeaderData().getCategories());
  455.             writeBlogPage();
  456.         }
  457.     }
  458.     
  459.     public synchronized void updateEntry(BlogEntry be) throws SQLException, IOException
  460.     {
  461.         /*BlogEntry oldEntry = getEntry(be.getID());        
  462.  
  463.         super.updateEntry(be);
  464.         
  465.         Statement st = conn.createStatement();
  466.         ResultSet rs = st.executeQuery(
  467.             "SELECT * FROM " + TABLE + " WHERE ID = " + be.getID());
  468.         rs.next();
  469.         String apage = rs.getString(ARCPAGE);
  470.         st.close(); */
  471.         
  472.         PreparedStatement ps = conn.prepareStatement
  473.         (
  474.                 "UPDATE " + TABLE + " SET " +
  475.                 TIMESTAMP + " = ?, " +
  476.                 TITLE + " = ?, " +
  477.                 CATEGORIES + " = ?, " +
  478.                 ENTRY + " = ?, " +
  479.                 DRAFT + " = ?, " +
  480.                 MODIFIED + " = ?, " +
  481.                 AUTHOR + " = ? WHERE " + ID + " = ?"
  482.         );
  483.         
  484.         ps.setTimestamp(1, be.getTimestamp());
  485.         ps.setString(2, be.getTitle());
  486.         ps.setString(3, catsString(be.getHeaderData().getCategories()));
  487.         ps.setString(4, be.getEntryText());
  488.         ps.setBoolean(5, be.getHeaderData().isDraft());
  489.         ps.setTimestamp(6, be.getHeaderData().getLastModified());
  490.         ps.setString(7, be.getHeaderData().getAuthor());
  491.         ps.setInt(8, be.getID());
  492.         
  493.         ps.executeUpdate();
  494.         ps.close();       
  495.  
  496.         rebuildBlog();
  497.     }
  498.     
  499.     public long[] getAllEntryIDs() throws SQLException
  500.     {
  501.         Statement st = conn.createStatement();
  502.         Vector v = new Vector();
  503.         ResultSet rs = st.executeQuery("SELECT * FROM " + TABLE);
  504.         while(rs.next())
  505.         {
  506.             long id = rs.getInt(ID);
  507.             v.add(new Long(id));
  508.         }
  509.         st.close();
  510.         
  511.         long ids[] = new long[v.size()];
  512.         for(int i = 0; i < ids.length; i++)
  513.         {
  514.             Long id = (Long)v.elementAt(i);
  515.             ids[i] = id.longValue();
  516.         }
  517.         
  518.         return ids;
  519.     }
  520.     
  521.     public synchronized void rebuildBlog() throws SQLException, IOException
  522.     {
  523.         DatedArchivePage.setArchiveRangeFormat(vars.getArchiveRangeFormat());
  524.         //expire entries less than baseDate
  525.         Timestamp base = new Timestamp(baseDate.getTime());
  526.            update("UPDATE " + TABLE + " SET " + ARCPAGE + "='" + EXPIRED + "' " +
  527.                   "WHERE " + TIMESTAMP + " < " + "'" + base + "'");
  528.            
  529.         //create archive pages for entries greater than baseDate based on arc policy
  530.         DatedArchivePage cur = null;        
  531.         Statement st = conn.createStatement();
  532.         ResultSet rs = st.executeQuery(
  533.             "SELECT * FROM " + TABLE + " WHERE " + TIMESTAMP + " > " +
  534.             "'" + base + "' AND " + DRAFT + " <> 'true'" + " ORDER BY " + TIMESTAMP + " ASC");
  535.         
  536.         Vector arcPages = new Vector();                
  537.         while(rs.next())
  538.         {
  539.             Timestamp ts = rs.getTimestamp(TIMESTAMP);
  540.             //current record greater than current page date
  541.             if(cur == null || cur.getExpirationDate().compareTo(ts) < 0)
  542.                {
  543.                    java.util.Date d1 = new java.util.Date(ts.getTime());
  544.                    java.util.Date d2 = addIntervalToDate(ts, daysInterval - 1);
  545.                    
  546.                    if(archivePolicy == ARCHIVE_MONTHLY)
  547.                    {
  548.                        Calendar cal = GregorianCalendar.getInstance();
  549.                        cal.setTime(d1);
  550.                        cal.set(Calendar.DAY_OF_MONTH, 1);
  551.                        d1 = cal.getTime();
  552.                    
  553.                        cal.add(Calendar.MONTH, 1);
  554.                        cal.add(Calendar.DATE, -1);
  555.                        d2 = cal.getTime();               
  556.                    }
  557.                    else if(archivePolicy == ARCHIVE_WEEKLY)
  558.                    {
  559.                        Calendar cal = GregorianCalendar.getInstance();
  560.                        cal.setTime(d1);
  561.                     //cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
  562.                     //bug fix - in some countries Monday is the 1st day of the week
  563.                     cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
  564.                     d1 = cal.getTime();                    
  565.                     //cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
  566.                     cal.add(Calendar.DAY_OF_MONTH, 6);
  567.                     d2 =  cal.getTime();
  568.                     
  569.                     //java.text.SimpleDateFormat mdf = new java.text.SimpleDateFormat("EEEE yyyy/MM/dd");
  570.                     //System.out.println(mdf.format(d1) + " - " + mdf.format(d2));                     
  571.                    }
  572.                    
  573.                    cur = new DatedArchivePage(
  574.                     getArchiveDirectory().getAbsolutePath(), d1, d2);               
  575.                    arcPages.add(cur);    
  576.                }
  577.                
  578.                int id = rs.getInt(ID);
  579.                update("UPDATE " + TABLE + 
  580.                 " SET " + ARCPAGE + "='" + cur.getName() +  
  581.                 "' WHERE " + ID + "=" + id);                           
  582.         }
  583.         
  584.         st.close();
  585.         clearUpdatedPages();
  586.         
  587.         //delete the old archive pages
  588.         File oldArcs[] = DatedArchivePage.listDatedArchivePages(getArchiveDirectory());
  589.         try
  590.         {
  591.             for(int i = 0; i < oldArcs.length; i++)
  592.                 oldArcs[i].delete();
  593.         }
  594.         catch(Exception ex)
  595.         {
  596.             //System.out.println("Couldn't delete archvie file");
  597.         }        
  598.         
  599.         //create blank arc pages so we know what to list
  600.         try
  601.         {
  602.             for(int i = 0; i < arcPages.size(); i++)
  603.                 ((File)arcPages.elementAt(i)).createNewFile();
  604.         }
  605.         catch(Exception ex){}        
  606.         
  607.         //write the archive pages
  608.         for(int i = 0; i < arcPages.size(); i++)
  609.         {
  610.             File f = (File)arcPages.elementAt(i);
  611.             writeArchivePage(f.getName());
  612.         }        
  613.         
  614.         try{
  615.         curArcPage = (DatedArchivePage)arcPages.lastElement();
  616.         }catch(Exception ex){}        
  617.         
  618.         String categories[] = vars.getCategories();
  619.         for(int i = 0; i < categories.length; i++)
  620.         {
  621.             CategoryPage cp = 
  622.                 new CategoryPage(getArchiveDirectory().getAbsolutePath(), 
  623.                 categories[i]);
  624.             try{cp.delete();}
  625.             catch(Exception ex){}
  626.             writeCategoryPage(categories[i]);
  627.         }
  628.         
  629.         writeIndexPage();        
  630.         writeBlogPage();        
  631.     }
  632.     
  633.     public synchronized BlogEntryHeaderData[] getCurrentEntries() throws SQLException
  634.     {
  635.         Timestamp ts = new Timestamp(baseDate.getTime());
  636.         Statement st = conn.createStatement();
  637.         ResultSet rs = st.executeQuery(
  638.             "SELECT * FROM " + TABLE + 
  639.             " WHERE " + TIMESTAMP + " > " + "'" + ts + "'" + 
  640.             " AND " + DRAFT + " = '" + false + "'" + 
  641.             " ORDER BY " + TIMESTAMP + " DESC");
  642.         BlogEntryHeaderData hd[] = listHeaders(rs);
  643.         st.close();
  644.         
  645.         if(limitFrontPageEntries && (hd.length > frontPageEntryLimit))
  646.         {
  647.             BlogEntryHeaderData lhd[] = new BlogEntryHeaderData[frontPageEntryLimit];
  648.             for(int i = 0; i < lhd.length; i++)
  649.                 lhd[i] = hd[i];
  650.             
  651.             return lhd;
  652.         }
  653.         
  654.         return hd;    
  655.     }
  656.     
  657.     public synchronized BlogEntryHeaderData[] getExpiredEntries() throws SQLException
  658.     {
  659.         Statement st = conn.createStatement();
  660.         ResultSet rs = st.executeQuery(
  661.             "SELECT * FROM " + TABLE + 
  662.             " WHERE " + ARCPAGE + " = " + "'" + EXPIRED + "'" +
  663.             " AND " + DRAFT + " = '" + false + "'" +  
  664.             " ORDER BY " + TIMESTAMP + " DESC");
  665.         BlogEntryHeaderData hd[] = listHeaders(rs);
  666.         st.close();
  667.         
  668.         return hd;
  669.     }
  670.     
  671.     public synchronized BlogEntryHeaderData[] getDrafts() throws SQLException
  672.     {
  673.         Statement st = conn.createStatement();
  674.         ResultSet rs = st.executeQuery(
  675.             "SELECT * FROM " + TABLE + 
  676.             " WHERE " + DRAFT + " = " + "'" + true + "'" + 
  677.             " ORDER BY " + TIMESTAMP + " DESC");
  678.         BlogEntryHeaderData hd[] = listHeaders(rs);
  679.         st.close();
  680.         
  681.         return hd;
  682.     }
  683.     
  684.     public synchronized void deleteEntries(int ids[]) throws SQLException, IOException
  685.     {
  686.         if(ids == null) return;
  687.         for(int i = 0; i < ids.length; i++)
  688.             update("DELETE FROM " + TABLE + " WHERE ID = " + ids[i]);
  689.         rebuildBlog();
  690.     }
  691.     
  692.     public synchronized void deleteEntry(int id) throws SQLException, IOException
  693.     {
  694.        int ids[] = new int[1];
  695.        ids[0] = id;
  696.        deleteEntries(ids);
  697.     }    
  698.     
  699.     protected String computeLimitArgument(PreparedStatement query, int entryLimit) 
  700.     throws SQLException
  701.     {           
  702.         ResultSet rs = query.executeQuery();
  703.             
  704.         int count = 0;
  705.         while(rs.next())
  706.         {            
  707.              count++;
  708.         }
  709.                 
  710.         String limit = "";
  711.         if(count > entryLimit)
  712.         {
  713.             if(isWriteAscending())
  714.                 limit = "LIMIT "  + (count - entryLimit) + " " +  entryLimit;
  715.             else
  716.                 limit = "LIMIT " + "0 " + entryLimit;
  717.         }
  718.         
  719.         return limit;        
  720.     }
  721.     
  722.     protected java.util.Date addIntervalToDate(java.util.Date date, int i)
  723.     {
  724.         Calendar cal = Calendar.getInstance();
  725.         cal.setTime(date);
  726.            cal.add(Calendar.DATE, i);
  727.             
  728.         return cal.getTime();
  729.     }
  730.     
  731.     public java.util.Date getBaseDate()
  732.     {
  733.         return baseDate;
  734.     }
  735.     
  736.     public void setBaseDate(java.util.Date d)
  737.     {        
  738.         //set to 12:00 AM 
  739.         Calendar cal = Calendar.getInstance();
  740.         cal.setTime(d);       
  741.         cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 
  742.             cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);       
  743.          baseDate = cal.getTime();
  744.     }
  745.     
  746.     public void setDaysArchiveInterval(int i)
  747.     {
  748.         if(i > 0)
  749.             daysInterval = i;
  750.     }
  751.     
  752.     public int getDaysArchiveInterval()
  753.     {
  754.         return daysInterval;
  755.     }    
  756.   
  757.     public void setGenerateRss(boolean b)
  758.     {
  759.         generateRss = b;
  760.         if(!generateRss)
  761.         {
  762.             File f = new File(
  763.                 assemblePath(getHtmlDirectory().getAbsolutePath(),
  764.                 RSS_FILENAME));
  765.             removeUpdatedPage(f);
  766.             f.delete();                
  767.         }    
  768.     }
  769.     
  770.     public void setWriteFullRssEntries(boolean b)
  771.     {
  772.         isWriteFullRssEntries = b;
  773.     }
  774.     
  775.     public boolean isWriteFullRssEntries()
  776.     {
  777.         return isWriteFullRssEntries;
  778.     }
  779.     
  780.     public boolean isGenerateRss()
  781.     {
  782.         return generateRss;
  783.     }
  784.     
  785.     public void setLimitFrontPageEntries(boolean b)
  786.     {
  787.         limitFrontPageEntries = b;
  788.     }
  789.     
  790.     public boolean isLimitFrontPageEntries()
  791.     {
  792.         return limitFrontPageEntries;
  793.     }
  794.     
  795.     public void setFrontPageEntryLimit(int l)
  796.     {
  797.         if(l > 0) frontPageEntryLimit = l;
  798.     }
  799.     
  800.     public int getFrontPageEntryLimit()
  801.     {
  802.         return frontPageEntryLimit;
  803.     }
  804.     
  805.     public void setArchiveListAscending(boolean b)
  806.     {
  807.         arcListAscending = b;
  808.         DatedArchivePage.setListAscending(b);    
  809.     }
  810.     
  811.     public boolean isArchiveListAscending()
  812.     {
  813.         return arcListAscending;
  814.     }
  815.     
  816.     public void setLimitCategoryPageEntries(boolean b)
  817.     {
  818.         limitCatPageEntries = b;
  819.     }
  820.     
  821.     public boolean isLimitCategoryPageEntries()
  822.     {
  823.         return limitCatPageEntries;
  824.     }
  825.     
  826.     public void setCategoryPageEntryLimit(int l)
  827.     {
  828.         if(l > 0)catPageEntryLimit = l;
  829.     }
  830.     
  831.     public int getCategoryPageEntryLimit()
  832.     {
  833.         return catPageEntryLimit;
  834.     }
  835.     
  836.     public boolean isWriteAscending()
  837.     {
  838.         return ascOrDesc.equals(ASC);    
  839.     }
  840.     
  841.     public void setWriteAscending(boolean b)
  842.     {
  843.         if(b)
  844.             ascOrDesc = ASC;
  845.         else
  846.             ascOrDesc = DESC;            
  847.     } 
  848.     
  849.     public void addCategory(String cat) 
  850.     {
  851.         vars.addCategory(cat);
  852.     }
  853.     
  854.     public void addAuthor(Author a)
  855.     {
  856.         vars.addAuthor(a);    
  857.     }
  858.     
  859.     public synchronized void renameCategory(String oldCat, String newCat) throws SQLException
  860.     {        
  861.         String ca[] = vars.getCategories();
  862.         boolean contains = false;
  863.         for(int i = 0; i < ca.length; i++)
  864.         {
  865.             if(ca[i].equals(oldCat))
  866.             {
  867.                 contains = true;
  868.                 break;
  869.             }    
  870.         }
  871.         
  872.         if(!contains)
  873.             return;
  874.        
  875.        PreparedStatement ps = conn.prepareStatement
  876.         ("SELECT * FROM " + TABLE +
  877.          " WHERE " + CATEGORIES + " LIKE CONCAT('%', CONCAT(?, '%'))");
  878.          
  879.         //String theCat = "<" + oldCat + ">";
  880.           ps.setString(1, "<" + oldCat + ">");
  881.           ResultSet rs = ps.executeQuery();
  882.           while(rs.next())
  883.           {
  884.               String c = rs.getString(CATEGORIES);
  885.               int id = rs.getInt(ID);
  886.             int s = c.indexOf(oldCat);
  887.             int e = s + oldCat.length(); 
  888.         
  889.             StringBuffer sb = new StringBuffer(c);
  890.             sb.replace(s, e, newCat);
  891.             //System.out.println(sb.toString());
  892.             
  893.             PreparedStatement update = conn.prepareStatement
  894.             (
  895.                 "UPDATE " + TABLE + " SET " +
  896.                  CATEGORIES + " = ? " +               
  897.                 "WHERE " + ID + " = ?"
  898.             );        
  899.             update.setString(1, sb.toString());
  900.             update.setInt(2, id);
  901.             update.executeUpdate();
  902.             update.close();                          
  903.           }
  904.           
  905.           ps.close();         
  906.                   
  907.         vars.removeCategory(oldCat);
  908.         vars.addCategory(newCat);    
  909.         CategoryPage cp = new CategoryPage(
  910.                 getArchiveDirectory().getAbsolutePath(), oldCat);
  911.         if(cp.exists())
  912.             cp.delete();
  913.         removeUpdatedPage(cp);    
  914.     }
  915.     
  916.     public synchronized void removeCategory(String cat) throws SQLException
  917.     {        
  918.        PreparedStatement ps = conn.prepareStatement
  919.         ("SELECT * FROM " + TABLE +
  920.          " WHERE " + CATEGORIES + " LIKE CONCAT('%', CONCAT(?, '%'))");
  921.          
  922.         String theCat = "<" + cat + ">";
  923.           ps.setString(1, theCat);
  924.           ResultSet rs = ps.executeQuery();
  925.           while(rs.next())
  926.           {
  927.               String c = rs.getString(CATEGORIES);
  928.               int id = rs.getInt(ID);
  929.             int s = c.indexOf(theCat);
  930.         
  931.             // + 1 gets rid of trailing space
  932.             // seems kind of dangerous, but it works...
  933.             int e = s + theCat.length() + 1; 
  934.         
  935.             StringBuffer sb = new StringBuffer(c);
  936.             sb.delete(s, e);
  937.             //System.out.println(sb.toString());
  938.             
  939.             PreparedStatement update = conn.prepareStatement
  940.             (
  941.                 "UPDATE " + TABLE + " SET " +
  942.                  CATEGORIES + " = ? " +               
  943.                 "WHERE " + ID + " = ?"
  944.             );        
  945.             update.setString(1, sb.toString());
  946.             update.setInt(2, id);
  947.             update.executeUpdate();
  948.             update.close();                          
  949.           }
  950.           
  951.           ps.close();         
  952.                   
  953.         vars.removeCategory(cat);    
  954.         CategoryPage cp = new CategoryPage(
  955.                 getArchiveDirectory().getAbsolutePath(), cat);
  956.         if(cp.exists())
  957.             cp.delete();
  958.         removeUpdatedPage(cp);
  959.     }
  960.     
  961.     public void removeAuthor(Author a) throws SQLException
  962.     {        
  963.         PreparedStatement ps = conn.prepareStatement
  964.         ("SELECT * FROM " + TABLE +
  965.          " WHERE " + AUTHOR + " = ?");
  966.          
  967.         ps.setString(1, a.getName());
  968.           ResultSet rs = ps.executeQuery();
  969.           while(rs.next())
  970.           {
  971.               int id = rs.getInt(ID);
  972.                PreparedStatement update = conn.prepareStatement
  973.             (
  974.                 "UPDATE " + TABLE + " SET " +
  975.                  AUTHOR + " = ? " +               
  976.                 "WHERE " + ID + " = ?"
  977.             );        
  978.             update.setString(1, "");
  979.             update.setInt(2, id);
  980.             update.executeUpdate();
  981.             update.close();                          
  982.           }
  983.           
  984.           ps.close();                 
  985.         vars.removeAuthor(a.getName());
  986.     }
  987.     
  988.     public void editAuthor(Author oldAuth, Author newAuth) throws SQLException
  989.     {        
  990.         if(oldAuth.getName().equals(newAuth.getName()))
  991.         {
  992.             vars.addAuthor(newAuth); //update
  993.             return;    
  994.         }
  995.         
  996.         PreparedStatement ps = conn.prepareStatement
  997.         ("SELECT * FROM " + TABLE +
  998.          " WHERE " + AUTHOR + " = ?");
  999.          
  1000.         ps.setString(1, oldAuth.getName());
  1001.           ResultSet rs = ps.executeQuery();
  1002.           while(rs.next())
  1003.           {
  1004.               int id = rs.getInt(ID);
  1005.                PreparedStatement update = conn.prepareStatement
  1006.             (
  1007.                 "UPDATE " + TABLE + " SET " +
  1008.                  AUTHOR + " = ? " +               
  1009.                 "WHERE " + ID + " = ?"
  1010.             );        
  1011.             update.setString(1, newAuth.getName());
  1012.             update.setInt(2, id);
  1013.             update.executeUpdate();
  1014.             update.close();                          
  1015.           }
  1016.           
  1017.           ps.close();                 
  1018.         vars.removeAuthor(oldAuth.getName());
  1019.         vars.addAuthor(newAuth);
  1020.     }
  1021.     
  1022.     public String[] getCategories()
  1023.     {   
  1024.         return vars.getCategories();
  1025.     }
  1026.     
  1027.     public Author[] getAuthors()
  1028.     {
  1029.         return vars.getAuthors();    
  1030.     }
  1031.     
  1032.     public DatedArchivePage[] getDatedArchivePages()
  1033.     {
  1034.         return DatedArchivePage.listDatedArchivePages(getArchiveDirectory());
  1035.     }
  1036.     
  1037.     public DatedArchivePage getMostRecentDatedArchivePage()
  1038.     {
  1039.         if(curArcPage == null)
  1040.         {
  1041.             try
  1042.             {
  1043.                 //TODO Fix so that an Asc/desc arc list returns the right page
  1044.                 DatedArchivePage p[] = 
  1045.                     DatedArchivePage.listDatedArchivePages(getArchiveDirectory());                
  1046.                 return p[p.length - 1]; //get the most recent page
  1047.             }
  1048.             catch(Exception ex){}
  1049.         }
  1050.         
  1051.         return curArcPage;
  1052.     }
  1053.     
  1054.     public void setLastPublishDate(java.util.Date d)
  1055.     {
  1056.         lastPublishDate = d;
  1057.     }
  1058.     
  1059.     public java.util.Date getLastPublishDate()
  1060.     {
  1061.         return lastPublishDate;
  1062.     }
  1063.     
  1064.     private String assemblePath(String p1, String p2)
  1065.     {
  1066.         String sep = System.getProperty("file.separator");
  1067.         if(!p1.endsWith(sep))
  1068.             p1 += sep;
  1069.         
  1070.         return p1 + p2;
  1071.     }
  1072.         
  1073. }